use crate::db::dao::user_group_user::UserGroupUserDao;
use crate::db::{dao, po};
use crate::dto;
use crate::service::error::Error;
use std::sync::Arc;

#[async_trait::async_trait]
pub trait UserGroupUserService: Send + Sync {
    async fn list(
        &self,
        filter: &dto::core::user_group_user::Filter,
        offset: u64,
        limit: u64,
    ) -> Result<Vec<dto::core::user_group_user::UserGroupUser>, Error>;
}

pub struct DefaultUserGroupUserService {
    user_grou_user_dao: Arc<dyn UserGroupUserDao>,
}

impl DefaultUserGroupUserService {
    pub fn new(user_grou_user_dao: Arc<dyn UserGroupUserDao>) -> Self {
        DefaultUserGroupUserService { user_grou_user_dao }
    }
}

#[async_trait::async_trait]
impl UserGroupUserService for DefaultUserGroupUserService {
    async fn list(
        &self,
        filter: &dto::core::user_group_user::Filter,
        offset: u64,
        limit: u64,
    ) -> Result<Vec<dto::core::user_group_user::UserGroupUser>, Error> {
        let po_list = self
            .user_grou_user_dao
            .find(dao::FindParams {
                filter: filter.into(),
                offset: Some(offset),
                limit: Some(limit),
                ..Default::default()
            })
            .await?;

        let list = wanmesh_common::util::slice_try_to(po_list.as_slice())?;

        Ok(list)
    }
}

impl TryFrom<&po::user_group_user::Model> for dto::core::user_group_user::UserGroupUser {
    type Error = anyhow::Error;

    fn try_from(value: &po::user_group_user::Model) -> Result<Self, Self::Error> {
        Ok(Self {
            user_group_id: value.user_group_id.clone(),
            user_id: value.user_id.clone(),
        })
    }
}

impl TryFrom<po::user_group_user::Model> for dto::core::user_group_user::UserGroupUser {
    type Error = anyhow::Error;
    fn try_from(value: po::user_group_user::Model) -> Result<Self, Self::Error> {
        Self::try_from(&value)
    }
}

impl From<&dto::core::user_group_user::Filter> for dao::user_group_user::Filter {
    fn from(value: &dto::core::user_group_user::Filter) -> Self {
        Self {
            user_group_id: value.user_group_id.clone(),
            user_id: value.user_id.clone(),
        }
    }
}
